#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
from numpy import *
import talib
from functools import reduce

class BasicStatsOpe():

    def power(self,mat):
        '''
        :输入矩阵,数据集格式为矩阵
        :return:输出每个元素对应的平方值
        '''
        pow2 = multiply(mat,mat)
        return pow2

    def abs(self,mat):
        '''
        :输入矩阵,数据集格式为矩阵
        :return:输出每个元素对应的绝对值
        '''
        ret = abs(mat)
        return ret

    def log(self,mat):
        '''
        :输入矩阵,数据集格式为矩阵
        :return:输出每个元素对应的log
        '''
        ret = np.log(mat)
        return ret

    def MovAvg(self,mat,param):
        '''
        :输入矩阵,数据集格式为矩阵
        :return:输出为相应矩阵的移动平均值
        '''
        ret = np.zeros(np.shape(mat))*np.nan
        for k in range(np.shape(mat)[1]):
            idx = np.isnan((mat[:,k])) == False
            temp = np.copy(mat[idx,k])
            rettemp = np.zeros(np.shape(temp))*np.nan
            for i in range(len(temp)):
                rettemp[i] = np.mean(temp[i-param+1:i+1])
            ret[idx,k] = np.copy(rettemp)
        return ret

    def Correlation(self,mat,mat2,step):
        '''
        :输入矩阵,数据集格式为矩阵,step为过去多少天
        :return:输出为相应2个矩阵的相关系数
        '''
        ret = np.zeros(np.shape(mat)) * np.nan
        for k in range(np.shape(mat)[1]):
            idx = np.isnan((mat[:, k])) == False
            temp = (np.copy(mat[idx, k]))  # .reshape(len(np.copy(df[idx,k])),1)
            temp2 = (np.copy(mat2[idx, k]))  # .reshape(len(np.copy(df[idx,k])),1)
            rettemp = np.zeros(np.shape(temp)) * np.nan
            for i in range(len(temp)):
                rettemp[i] = np.mean(multiply((temp[i - step + 1:i + 1] - np.mean(temp[i - step + 1:i + 1])),
                                              (temp2[i - step + 1:i + 1] - mean(temp2[i - step + 1:i + 1])))) / (
                                         std(temp[i - step + 1:i + 1]) * std(temp2[i - step + 1:i + 1]))
            ret[idx, k] = np.copy(rettemp)
        return ret

    def Covariance(self,mat,mat2,step):
        '''
        :输入矩阵,数据集格式为矩阵,step为过去多少天
        :return:输出为相应2个矩阵的协方差
        '''
        ret = np.zeros(np.shape(mat))*np.nan
        for k in range(np.shape(mat)[1]):
            idx = np.isnan((mat[:, k])) == False
            temp = (np.copy(mat[idx, k]))
            temp2 = np.copy(mat2[idx, k])
            rettemp = np.zeros(np.shape(temp)) * np.nan
            for i in range(len(temp)):
                rettemp[i] = np.mean(multiply((temp[i - step + 1:i + 1] - np.mean(temp[i - step + 1:i + 1])),
                                              (temp2[i - step + 1:i + 1] - mean(temp2[i - step + 1:i + 1]))))
            ret[idx,k] = np.copy(rettemp)
        return ret

    def DECAY_LINEAR(self,mat,step):
        '''
        :输入矩阵,数据集格式为矩阵,step为过去多少天
        :return:输出decay
        '''
        ret = np.zeros(np.shape(mat))*np.nan
        for k in range(np.shape(mat)[1]):
            idx = np.isnan((mat[:, k])) == False
            temp = (np.copy(mat[idx, k]))
            rettemp = np.zeros(np.shape(temp)) * np.nan
            for i in range(step,len(temp)):
                rettemp[i] = np.sum(multiply([p for p in arange(0,step)],temp[i - step + 1:i + 1]))/np.sum(range(step))
            ret[idx,k] = np.copy(rettemp)
        return ret

    def DELTA (self,mat,step):
        '''
        :输入矩阵,数据集格式为矩阵,step为过去多少天
        :return:输出delta
        '''
        ret = np.zeros(np.shape(mat))*np.nan
        for k in range(np.shape(mat)[1]):
            idx = np.isnan((mat[:, k])) == False
            temp = (np.copy(mat[idx, k]))
            rettemp = np.zeros(np.shape(temp)) * np.nan
            for i in range(step,len(temp)):
                rettemp[i] = temp[i] - temp[i-step]
            ret[idx,k] = np.copy(rettemp)
        return ret

    def MAX (self,mat,step):
        '''
        :输入矩阵,数据集格式为矩阵,step为过去多少天
        :return:输出为时间序列中最大值
        '''
        ret = np.zeros(np.shape(mat))*np.nan
        for k in range(np.shape(mat)[1]):
            idx = np.isnan((mat[:, k])) == False
            temp = (np.copy(mat[idx, k]))
            rettemp = np.zeros(np.shape(temp)) * np.nan
            for i in range(step,len(temp)):
                rettemp[i] = np.max(temp[i-step+1:i+1])
            ret[idx,k] = np.copy(rettemp)
        return ret

    def MIN (self,mat,step):
        '''
        :输入矩阵,数据集格式为矩阵,step为过去多少天
        :return:输出为时间序列中最小值
        '''
        ret = np.zeros(np.shape(mat))*np.nan
        for k in range(np.shape(mat)[1]):
            idx = np.isnan((mat[:, k])) == False
            temp = (np.copy(mat[idx, k]))
            rettemp = np.zeros(np.shape(temp)) * np.nan
            for i in range(step,len(temp)):
                rettemp[i] = np.min(temp[i-step+1:i+1])
            ret[idx,k] = np.copy(rettemp)
        return ret

    def product (self,mat,step):
        '''
        :输入矩阵,数据集格式为矩阵,step为过去多少天
        :return:输出为时间序列n天相乘
        '''
        ret = np.zeros(np.shape(mat))*np.nan
        for k in range(np.shape(mat)[1]):
            idx = np.isnan((mat[:, k])) == False
            temp = (np.copy(mat[idx, k]))
            rettemp = np.zeros(np.shape(temp)) * np.nan
            for i in range(step,len(temp)):
                rettemp[i] = reduce(lambda x,y:x*y,temp[i-step+1:i+1])
            ret[idx,k] = np.copy(rettemp)
        return ret

    def Scale (self,mat,step):
        '''
        :输入矩阵,数据集格式为矩阵,step为过去多少天
        :return:输出为标准归一化结果
        '''
        ret = np.zeros(np.shape(mat))*np.nan
        for k in range(np.shape(mat)[1]):
            idx = np.isnan((mat[:, k])) == False
            temp = (np.copy(mat[idx, k]))
            rettemp = np.zeros(np.shape(temp)) * np.nan
            for i in range(step,len(temp)):
                rettemp[i] = (temp[i] - np.mean(temp[i-step+1:i+1]))/np.std(temp[i-step+1:i+1])
            ret[idx,k] = np.copy(rettemp)
        return ret

    def STDDEV (self,mat,step):
        '''
        :输入矩阵,数据集格式为矩阵,step为过去多少天
        :return:输出为在时间序列方向上step日内的移动标准差
        '''
        ret = np.zeros(np.shape(mat))*np.nan
        for k in range(np.shape(mat)[1]):
            idx = np.isnan((mat[:, k])) == False
            temp = (np.copy(mat[idx, k]))
            rettemp = np.zeros(np.shape(temp)) * np.nan
            for i in range(step,len(temp)):
                rettemp[i] = np.std(temp[i-step+1:i+1])
            ret[idx,k] = np.copy(rettemp)
        return ret

    def Sum (self,mat,step):
        '''
        :输入矩阵,数据集格式为矩阵,step为过去多少天
        :return:输出为x在时间序列方向上d日内的和
        '''
        ret = np.zeros(np.shape(mat))*np.nan
        for k in range(np.shape(mat)[1]):
            idx = np.isnan((mat[:, k])) == False
            temp = (np.copy(mat[idx, k]))
            rettemp = np.zeros(np.shape(temp)) * np.nan
            for i in range(step,len(temp)):
                rettemp[i] = np.sum(temp[i-step+1:i+1])
            ret[idx,k] = np.copy(rettemp)
        return ret

    def TS_RANGE (self,mat,step):
        '''
        :输入矩阵,数据集格式为矩阵,step为过去多少天
        :return:输出为x在时间序列方向上d日内的极差
        '''
        ret = np.zeros(np.shape(mat))*np.nan
        for k in range(np.shape(mat)[1]):
            idx = np.isnan((mat[:, k])) == False
            temp = (np.copy(mat[idx, k]))
            rettemp = np.zeros(np.shape(temp)) * np.nan
            for i in range(step,len(temp)):
                rettemp[i] = np.max(temp[i-step+1:i+1]) - np.min(temp[i-step+1:i+1])
            ret[idx,k] = np.copy(rettemp)
        return ret


    def Return(self,mat ,n):
        '''
        :输入矩阵,数据集格式为矩阵
        :return:输出每个元素对应的绝对值
        '''
        ret = np.zeros(np.shape(mat))*np.nan
        for k in range(np.shape(mat)[1]):
            idx = np.isnan((mat[:,k])) == False
            temp = np.copy(mat[idx,k])
            rettemp = np.zeros(np.shape(temp))*np.nan
            for i in range(n, len(temp)):
                rettemp[i] = temp[i]/temp[i-n]-1
            ret[idx, k] = np.copy(rettemp)
        return ret

    def Skew(self, mat, param):
        '''
        :输入矩阵,数据集格式为矩阵
        :return:输出每个元素对应的偏度
        '''
        ret = np.zeros(np.shape(mat))*np.nan
        y = np.shape(mat)[1]
        for k in range(y):
            idx = np.isnan((mat[:,k])) == False
            temp = np.copy(mat[idx,k])
            rettemp = np.zeros(np.shape(temp))*np.nan
            for i in range(1,len(temp)):
                m2 = np.std(temp[i-param+1:i+1],ddof=1)
                mm = np.mean(temp[i-param+1:i+1])
                m3 = np.mean(np.power(temp[i-param+1:i+1]-mm,3))
                rettemp[i] = m3/(m2**3)
            ret[idx,k] = np.copy(rettemp)
        return ret

    def Skew2(self, mat, n):
        '''
        :输入矩阵,数据集格式为矩阵
        :return:输出每个元素对应的偏度
        '''
        ret = np.zeros(np.shape(mat))*np.nan
        y = np.shape(mat)[1]
        for k in range(y):
            idx = np.isnan((mat[:,k]))==False
            temp = np.copy(mat[idx,k])
            rettemp = np.zeros(np.shape(temp))*np.nan
            df = pd.DataFrame(temp)
            print(k)
            x = len(temp)
            for i in range(n, x):
                rettemp[i] = df[0][i-n:i].skew()
            ret[idx, k] = np.copy(rettemp)
        return ret

    def ATR(self, mat, mat2, mat3, param):
        '''
        :输入矩阵,数据集格式为矩阵,mat为收盘价，mat2为当日最高价，mat3为最低价二维矩阵
        :return:输出为ATR
        '''
        ret = np.zeros(np.shape(mat)) * np.nan
        for k in range(np.shape(mat)[1]):
            idx = np.isnan((mat[:, k])) == False
            temp = np.copy(mat[idx, k])
            rettemp = np.zeros(np.shape(temp)) * np.nan
            idx2 = np.isnan((mat2[:, k])) == False
            temp2 = np.copy(mat2[idx, k])
            rettemp2 = np.zeros(np.shape(temp2)) * np.nan
            idx3 = np.isnan((mat3[:, k])) == False
            temp3 = np.copy(mat3[idx, k])
            rettemp3 = np.zeros(np.shape(temp3)) * np.nan
            for i in range(1, len(temp)):
                rettemp[i] = talib.ATR(temp2, temp3, temp, timeperiod=param)
            ret[idx, k] = np.copy(rettemp)
        return ret
    def MACD(self,mat,param1,param2,param3):
        '''
        :输入矩阵,数据集格式为矩阵,mat为收盘价，3个参数为macd快慢参数
        :return:输出为MACD
        '''
        ret = np.zeros(np.shape(mat))*np.nan
        for k in range(np.shape(mat)[1]):
            idx = np.isnan((mat[:,k])) == False
            temp = np.copy(mat[idx,k])
            rettemp = np.zeros(np.shape(temp))*np.nan
            rettemp,rettemp2,rettemp3 = talib.MACD(temp,fastperiod=param1, slowperiod=param2, signalperiod=param3)
            ret[idx,k] = np.copy(rettemp)
        return ret

if __name__ == '__main__':
    x = BasicStatsOpe()
    # print(x.Return(hc.Loddata('close_5m')[0:], 10))
    # print(x.Skew2(hc.Loddata('close_60m')[0:], 10))











